File: xil_rtio_data_stream.c

    1   /* Copyright 2007-2013 The MathWorks, Inc. */
    2   
    3   /* 
    4    * File: xil_rtio_data_stream.c
    5    *
    6    * SIL/PIL data stream over the rtIOStream
    7    * NOTE: the xil_ide_data_stream.c implementation does not use this module
    8    *
    9    */					 
   10   
   11   /* include XIL data stream interface to implement */
   12   #include "xil_data_stream.h"
   13   /* include XIL initialization interface to implement */
   14   #include "xil_interface_lib.h"
   15   /* include rtIOStream interface to use */
   16   #include "rtiostream.h"
   17   /* include Target-side rtIOStream utility APIs */
   18   #include "rtiostream_utils.h"
   19   
   20   /* define a buffer to be used for concatenating small 
   21    * data writes into chunks of reasonable size for transmission */
   22   #ifndef RTIOSTREAM_TX_BUFFER_BYTE_SIZE 
   23   #define RTIOSTREAM_TX_BUFFER_BYTE_SIZE 300 
   24   #endif
   25   
   26   #ifdef HOST_WORD_ADDRESSABLE_TESTING
   27   /* rtIOStream will handle data in single byte chunks 
   28    *
   29    * uint8_T can be > 8-bits for certain portable word sizes 
   30    * cases (e.g. C2000) so use native type instead */
   31   typedef unsigned char IOUnit_T;
   32   #else
   33   /* rtIOStream will handle data in MemUnit_T size chunks */
   34   typedef MemUnit_T IOUnit_T;
   35   #endif
   36   
   37   #define WRITE_DATA_AVAIL_SIZE (sizeof(uint32_T))
   38   #define COMMAND_COMPLETE_SIZE (sizeof(MemUnit_T))
   39   #define WRITE_DATA_AVAIL_IDX 0
   40   #define COMMAND_COMPLETE_IDX (WRITE_DATA_AVAIL_IDX + WRITE_DATA_AVAIL_SIZE)
   41   #define WRITE_DATA_BUFFER_IDX (COMMAND_COMPLETE_IDX + COMMAND_COMPLETE_SIZE)
   42   #define RTIOSTREAM_TX_BUFFER_MEMUNIT_SIZE (RTIOSTREAM_TX_BUFFER_BYTE_SIZE / MEM_UNIT_BYTES)
   43   /* WRITE_BUFFER_SIZE must be representable in uint32_T */
   44   #define WRITE_BUFFER_SIZE (WRITE_DATA_AVAIL_SIZE + COMMAND_COMPLETE_SIZE + RTIOSTREAM_TX_BUFFER_MEMUNIT_SIZE)
   45   #define USED_WRITE_BUFFER_SIZE (WRITE_DATA_AVAIL_SIZE + COMMAND_COMPLETE_SIZE + writeDataAvail)
   46   
   47   static IOUnit_T writeBuffer[WRITE_BUFFER_SIZE];
   48   static IOUnit_T * writeDataPtr;
   49   static uint32_T writeDataAvail;
   50   static MemUnit_T * commandComplete = (MemUnit_T *) &writeBuffer[COMMAND_COMPLETE_IDX];
   51   
   52   /* store stream handle returned by rtio data stream */
   53   static int streamID;
   54   
   55   /* call rtIOStreamBlockingSend */
   56   static XIL_DATA_STREAM_ERROR_CODE xilRtIOStreamSend(const IOUnit_T * srcPtr, uint32_T size) {
   57      XIL_DATA_STREAM_ERROR_CODE errorCode = XIL_DATA_STREAM_SUCCESS;
   58      int rtIOStreamErrorStatus;
   59   
   60      /* Blocks until all requested outgoing data is sent */
   61      rtIOStreamErrorStatus = rtIOStreamBlockingSend(streamID,
   62                                                    (const void *) srcPtr,
   63                                                    size);
   64                                                         
   65      if (rtIOStreamErrorStatus == RTIOSTREAM_ERROR) {
   66            errorCode = XIL_WRITE_DATA_ERROR;
   67      }
   68      
   69      return errorCode;
   70   }
   71   
   72   /* reset the write buffer */
   73   static void resetWriteBuffer(void) {
   74      writeDataAvail = 0;
   75      writeDataPtr = &writeBuffer[WRITE_DATA_BUFFER_IDX];
   76      /* ready for next command */
   77      *commandComplete = 0;
   78   }
   79   
   80   /* send pending writes */
   81   static XIL_DATA_STREAM_ERROR_CODE sendWriteBuffer(void) {
   82      XIL_DATA_STREAM_ERROR_CODE errorCode = XIL_DATA_STREAM_SUCCESS;
   83   #ifdef HOST_WORD_ADDRESSABLE_TESTING
   84      /* writeDataAvail is in terms of IOUnit_T (uint8_T) - convert to MemUnit_T's 
   85       * assume that writeDataAvail divides exactly */
   86      uint32_T writeDataAvailMemUnits = writeDataAvail / MEM_UNIT_BYTES;
   87   #else
   88      uint32_T writeDataAvailMemUnits = writeDataAvail;
   89   #endif
   90      /* update writeDataAvail in the writeBuffer */
   91      memcpy((void *) &writeBuffer[WRITE_DATA_AVAIL_IDX], &writeDataAvailMemUnits, sizeof(writeDataAvailMemUnits));
   92      if (xilRtIOStreamSend(&writeBuffer[WRITE_DATA_AVAIL_IDX], USED_WRITE_BUFFER_SIZE) != XIL_DATA_STREAM_SUCCESS) { 
   93         /* throw flush error */
   94         errorCode = XIL_DATA_FLUSH_ERROR;
   95         return errorCode;
   96      }
   97      /* reset */
   98      resetWriteBuffer();
   99      return errorCode;
  100   }
  101   
  102   XIL_INTERFACE_LIB_ERROR_CODE xilInit(const int argc, 
  103                                        void *argv[]) {   
  104      XIL_INTERFACE_LIB_ERROR_CODE errorCode = XIL_INTERFACE_LIB_SUCCESS;
  105      resetWriteBuffer();
  106      streamID = rtIOStreamOpen(argc, argv);
  107      if (streamID == RTIOSTREAM_ERROR) {
  108         errorCode = XIL_INTERFACE_LIB_ERROR;
  109      }
  110      return errorCode;
  111   }
  112   
  113   /* This function must be called prior to terminating the application in order to
  114    * ensure an orderly shutdown of communications - data will already have been sent */
  115   XIL_INTERFACE_LIB_ERROR_CODE xilTerminateComms(void) {
  116      int errorStatus;
  117      XIL_INTERFACE_LIB_ERROR_CODE errorCode = XIL_INTERFACE_LIB_SUCCESS;
  118      errorStatus = rtIOStreamClose(streamID);
  119      if (errorStatus == RTIOSTREAM_ERROR) {
  120         errorCode = XIL_INTERFACE_LIB_ERROR;
  121      }
  122      return errorCode;
  123   }
  124   
  125   
  126   XIL_DATA_STREAM_ERROR_CODE xilWriteData(const MemUnit_T * src, uint32_T size) {
  127      XIL_DATA_STREAM_ERROR_CODE errorCode = XIL_DATA_STREAM_SUCCESS;
  128      const IOUnit_T * srcPtr = (const IOUnit_T *) src;
  129      size_t transferAmount;
  130      uint32_T bufferAvail;
  131   
  132      /* block until all data is processed */
  133      while (size > 0) {      
  134         /* send if we have a full message worth of data */   
  135         if (writeDataAvail == RTIOSTREAM_TX_BUFFER_MEMUNIT_SIZE) {
  136            errorCode = sendWriteBuffer();
  137            if (errorCode != XIL_DATA_STREAM_SUCCESS) {
  138               return errorCode;
  139            }
  140         }
  141         bufferAvail = RTIOSTREAM_TX_BUFFER_MEMUNIT_SIZE - writeDataAvail;
  142         transferAmount = (size_t) MIN(bufferAvail, size);
  143         /* copy data into write buffer */
  144         memcpy((void *) writeDataPtr, srcPtr, transferAmount);
  145         size -= (uint32_T) transferAmount;
  146         writeDataAvail += (uint32_T) transferAmount;
  147         srcPtr += transferAmount;
  148         writeDataPtr += transferAmount;
  149      }
  150      return errorCode;
  151   }
  152   
  153   XIL_DATA_STREAM_ERROR_CODE xilReadData(MemUnit_T * dst, uint32_T size) {
  154      XIL_DATA_STREAM_ERROR_CODE errorCode = XIL_DATA_STREAM_SUCCESS;
  155      int rtIOStreamErrorStatus;
  156   
  157      /* Blocks until all requested incoming data is received */
  158      rtIOStreamErrorStatus = rtIOStreamBlockingRecv(streamID,
  159                                                    (void *) dst,
  160                                                    size);
  161      
  162      if (rtIOStreamErrorStatus == RTIOSTREAM_ERROR) {
  163          errorCode = XIL_READ_DATA_ERROR;
  164      }
  165      
  166      return errorCode;
  167   }
  168   
  169   XIL_DATA_STREAM_ERROR_CODE xilDataFlush(void) {
  170      XIL_DATA_STREAM_ERROR_CODE errorCode = XIL_DATA_STREAM_SUCCESS;
  171      /* final part of command */
  172      *commandComplete = 1;
  173      /* send the write buffer */
  174      errorCode = sendWriteBuffer();
  175      return errorCode;
  176   }
  177